/*---------------------------------------------------------------------
 * File name: hal_uart.cpp
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#include "stm32f30x_rcc.h"
#include "stm32f30x_dma.h"
#include "stm32f30x_gpio.h"
#include "stm32f30x_usart.h"
#include "stm32f30x_misc.h"
#include "buffer/simple_buffer.h"
#include "hal_uart.h"
#include "hal_gpio.h"
#include "hal_system.h"
#include "hal_config.h"
#if defined(USING_RT_THREAD)
#include "rtthread.h" 
#endif
/*
*/
//UART1 
#if UART1_ENABLE
#if UART1_RX_DMA_ENABLE
#if UART1_RX_DMA == DMA1_CHANNEL5
#define UART1_RX_DMA_CH DMA1_Channel5
#else
#error "UART1_RX_DMA incorrect."
#endif
#else
#define UART1_RX_DMA_CH nullptr
#endif

#if UART1_TX_DMA_ENABLE
#if UART1_TX_DMA == DMA1_CHANNEL4
#define UART1_TX_DMA_CH DMA1_Channel4
#define UART1_TX_DMA_CH_IRQN DMA1_Channel4_IRQn
#define UART1_TX_DMA_CH_IRQH DMA1_Channel4_IRQHandler
#define UART1_TX_DMA_IT_TC DMA1_IT_TC4
#else
#error "UART1_TX_DMA incorrect."
#endif
#else
#define UART1_TX_DMA_CH nullptr
#endif
#endif
//UART2 
#if UART2_ENABLE
#if UART2_RX_DMA_ENABLE
#if UART2_RX_DMA == DMA1_CHANNEL6
#define UART2_RX_DMA_CH DMA1_Channel6
#else
#error "UART2_RX_DMA incorrect."
#endif
#else
#define UART2_RX_DMA_CH nullptr
#endif

#if UART2_TX_DMA_ENABLE
#if UART2_TX_DMA == DMA1_CHANNEL7
#define UART2_TX_DMA_CH DMA1_Channel7
#define UART2_TX_DMA_CH_IRQN DMA1_Channel7_IRQn
#define UART2_TX_DMA_CH_IRQH DMA1_Channel7_IRQHandler
#define UART2_TX_DMA_IT_TC DMA1_IT_TC7
#else
#error "UART2_TX_DMA incorrect."
#endif
#else
#define UART2_TX_DMA_CH nullptr
#endif
#endif
//UART3 
#if UART3_ENABLE
#if UART3_RX_DMA_ENABLE
#if UART3_RX_DMA == DMA1_CHANNEL3
#define UART3_RX_DMA_CH DMA1_Channel3
#else
#error "UART3_RX_DMA incorrect."
#endif
#else
#define UART3_RX_DMA_CH nullptr
#endif

#if UART3_TX_DMA_ENABLE
#if UART3_TX_DMA == DMA1_CHANNEL2
#define UART3_TX_DMA_CH DMA1_Channel2
#define UART3_TX_DMA_CH_IRQN DMA1_Channel2_IRQn
#define UART3_TX_DMA_CH_IRQH DMA1_Channel2_IRQHandler
#define UART3_TX_DMA_IT_TC DMA1_IT_TC2
#else
#error "UART3_TX_DMA incorrect."
#endif
#else
#define UART3_TX_DMA_CH nullptr
#endif
#endif
//UART4 
#if UART4_ENABLE
#if UART4_RX_DMA_ENABLE
#if UART4_RX_DMA == DMA2_CHANNEL3
#define UART4_RX_DMA_CH DMA2_Channel3
#else
#error "UART4_RX_DMA incorrect."
#endif
#else
#define UART4_RX_DMA_CH nullptr
#endif

#if UART4_TX_DMA_ENABLE
#if UART4_TX_DMA == DMA2_CHANNEL5
#define UART4_TX_DMA_CH DMA2_Channel5
#define UART4_TX_DMA_CH_IRQN DMA2_Channel5_IRQn
#define UART4_TX_DMA_CH_IRQH DMA2_Channel5_IRQHandler
#define UART4_TX_DMA_IT_TC DMA2_IT_TC5
#else
#error "UART4_TX_DMA incorrect."
#endif
#else
#define UART4_TX_DMA_CH nullptr
#endif
#endif
//UART5 
#if UART5_ENABLE
#if UART5_RX_DMA_ENABLE || UART5_TX_DMA_ENABLE
#error "UART5 dosen't have DMA."
#endif
#endif

/*---------------------------------------------------
 *                   UART_Object
 *---------------------------------------------------*/
class UART_Object
{
public:
  UART_Object(USART_TypeDef *USARTx,
              DMA_Channel_TypeDef *DMA_Rx,
              DMA_Channel_TypeDef *DMA_Tx,
              uint8_t *dma_rx_buffer, int dma_rx_buffer_size,
              uint8_t *dma_tx_buffer, int dma_tx_buffer_size,
              SimpleBuffer<uint8_t> &rx_buffer,
              SimpleBuffer<uint8_t> &tx_buffer) :
    uart(USARTx),
    dma_rx(DMA_Rx),
    dma_tx(DMA_Tx),
    dma_rx_buffer(dma_rx_buffer),
    dma_tx_buffer(dma_tx_buffer),
    dma_rx_buffer_size(dma_rx_buffer_size),
    dma_tx_buffer_size(dma_tx_buffer_size),
    rx_buffer(rx_buffer),
    tx_buffer(tx_buffer),
    rx_busy(false),
    tx_busy(false)
  {}
  
  USART_TypeDef         *uart;
  DMA_Channel_TypeDef   *dma_rx;
  DMA_Channel_TypeDef   *dma_tx;
  uint8_t *dma_rx_buffer;
  uint8_t *dma_tx_buffer;
  int dma_rx_buffer_size;
  int dma_tx_buffer_size;
  SimpleBuffer<uint8_t> &rx_buffer;
  SimpleBuffer<uint8_t> &tx_buffer;
  bool rx_busy;
  bool tx_busy;
  
  void dma_rx_config();
  void dma_rx_start();
  void dma_rx_end();
  void dma_tx_config();
  void dma_tx_start();
  void dma_tx_end();
  void int_rx_config();
  void int_tx_config();
  void int_rx();
  void int_tx();
  void send();
  bool config(uint32_t cfg);
};
/*
*/
void UART_Object::dma_rx_config()
{
    DMA_InitTypeDef  DMA_InitStructure;
    
    DMA_DeInit(dma_rx);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&uart->RDR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)dma_rx_buffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = dma_rx_buffer_size;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //attention 
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    
    DMA_Init(dma_rx, &DMA_InitStructure);
    DMA_Cmd(dma_rx, DISABLE);
    
    USART_DMACmd(uart, USART_DMAReq_Rx, ENABLE); 
    USART_ITConfig(uart, USART_IT_IDLE, ENABLE);  //idle interrupt  
    USART_ClearITPendingBit(uart, USART_IT_IDLE);
}
/*
*/
void UART_Object::dma_tx_config()
{
  DMA_InitTypeDef  DMA_InitStructure;
  
  DMA_DeInit(dma_tx);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&uart->TDR);
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)dma_tx_buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = dma_tx_buffer_size;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;   
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  
  DMA_Init(dma_tx, &DMA_InitStructure);
  /* Enable DMA Stream Transfer Complete interrupt */
  DMA_ITConfig(dma_tx, DMA_IT_TC, ENABLE);
  /* DMA Stream disable first*/
  DMA_Cmd(dma_tx, DISABLE);
  
  USART_DMACmd(uart, USART_DMAReq_Tx, ENABLE);
}
/*
*/
void UART_Object::dma_tx_start()
{
  if(!tx_busy)
  {
    uint32_t sr = enter_critical();
    int number = tx_buffer.pop(dma_tx_buffer, dma_tx_buffer_size);
    exit_critical(sr);
    
    if(number > 0)
    {
      tx_busy = true;
      DMA_SetCurrDataCounter(dma_tx, number);
      DMA_Cmd(dma_tx, ENABLE);
    }
  }
}
/*
*/
void UART_Object::dma_tx_end()
{
  DMA_Cmd(dma_tx, DISABLE);
  tx_busy = false;
}
/*
*/
void UART_Object::dma_rx_start()
{
  if(!rx_busy)
  {
    rx_busy = true;
    DMA_SetCurrDataCounter(dma_rx, dma_rx_buffer_size);
    DMA_Cmd(dma_rx, ENABLE);
  }
}
/*
*/
void UART_Object::dma_rx_end()
{
  DMA_Cmd(dma_rx, DISABLE);
  int number = dma_rx_buffer_size - dma_rx->CNDTR;
  
  uint32_t sr = enter_critical();
  rx_buffer.push(dma_rx_buffer, number);
  exit_critical(sr);
  
  rx_busy = false;
}
/*
*/
void UART_Object::int_rx_config()
{
  USART_DMACmd(uart, USART_DMAReq_Rx, DISABLE); 
  USART_ITConfig(uart, USART_IT_RXNE, ENABLE); 
  USART_ClearITPendingBit(uart, USART_IT_RXNE);
}
/*
*/
void UART_Object::int_tx_config()
{
  USART_DMACmd(uart, USART_DMAReq_Tx, DISABLE);
  USART_ITConfig(uart, USART_IT_TXE, DISABLE); //Disable first 
  USART_ClearITPendingBit(uart, USART_IT_TXE);
}
/*
*/
void UART_Object::int_rx()
{
  uint8_t data = uart->RDR;
  
  uint32_t sr = enter_critical();
  rx_buffer.push(&data, 1);
  exit_critical(sr);
}
/*
*/
void UART_Object::int_tx()
{
  uint8_t data;
  
  uint32_t sr = enter_critical();
  int number = tx_buffer.pop(&data, 1);
  exit_critical(sr);
  
  if(number > 0) {
    uart->TDR = data;
  } else {
    USART_ITConfig(uart, USART_IT_TXE, DISABLE); 
  }
}
/*
*/
void UART_Object::send()
{
  if(dma_tx_buffer != nullptr) {
    dma_tx_start();
  } else {
    USART_ITConfig(uart, USART_IT_TXE, ENABLE);  //just enable interrupt
  }
}
/*
*/
bool UART_Object::config(uint32_t cfg)
{
  USART_InitTypeDef USART_InitStructure;
   
  //baud
  uint32_t tmp = UART_CFG_EXTRACT(cfg, BAUD);
  USART_InitStructure.USART_BaudRate = tmp;
  
  //data bits
  tmp = UART_CFG_EXTRACT(cfg, DATA);
  if(tmp == UART_DATA(8B)) {
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  } else if (tmp == UART_DATA(9B)) {
    USART_InitStructure.USART_WordLength = USART_WordLength_9b;
  } else {
    return false;
  }
  
  //parity
  tmp = UART_CFG_EXTRACT(cfg, PARITY);
  if(tmp == UART_PARITY(NONE)) {
    USART_InitStructure.USART_Parity = USART_Parity_No;
  } else if(tmp == UART_PARITY(ODD)) {
    USART_InitStructure.USART_Parity = USART_Parity_Odd;
  } else if(tmp == UART_PARITY(EVEN)) {
    USART_InitStructure.USART_Parity = USART_Parity_Even;
  } else {
    return false;
  }
   
  //stop bits
  tmp = UART_CFG_EXTRACT(cfg, STOP);
  if(tmp == UART_STOP(1B)) {
    USART_InitStructure.USART_StopBits = USART_StopBits_1;   
  } else if(tmp == UART_STOP(1B5)) {
    USART_InitStructure.USART_StopBits = USART_StopBits_1_5;   
  } else if(tmp == UART_STOP(2B)) {
    USART_InitStructure.USART_StopBits = USART_StopBits_2;   
  } else {
    return false;
  }
  
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_Cmd(uart, DISABLE);
  USART_Init(uart, &USART_InitStructure);
  USART_Cmd(uart, ENABLE);
  
  return true;
}

/*----------------------------------------
 *             UART1 Object
 *-----------------------------------------*/
#if UART1_ENABLE
#if UART1_RX_DMA_ENABLE
  static uint8_t uart1_rx_dma_buffer[UART1_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart1_rx_dma_buffer = nullptr;
#endif
#if UART1_TX_DMA_ENABLE
  static uint8_t uart1_tx_dma_buffer[UART1_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart1_tx_dma_buffer = nullptr;
#endif
  static uint8_t uart1_rx_buffer[UART1_RX_BUFFER_SIZE];
  static uint8_t uart1_tx_buffer[UART1_TX_BUFFER_SIZE];
  static SimpleBuffer<uint8_t> uart1_rx_sbuffer(uart1_rx_buffer, UART1_RX_BUFFER_SIZE);
  static SimpleBuffer<uint8_t> uart1_tx_sbuffer(uart1_tx_buffer, UART1_TX_BUFFER_SIZE);
  static UART_Object uart1(USART1, UART1_RX_DMA_CH, UART1_TX_DMA_CH,
                          uart1_rx_dma_buffer, UART1_RX_DMA_BUFFER_SIZE,
                          uart1_tx_dma_buffer, UART1_TX_DMA_BUFFER_SIZE,
                          uart1_rx_sbuffer,
                          uart1_tx_sbuffer);
#endif
/*----------------------------------------
 *             UART2 Object
 *-----------------------------------------*/
#if UART2_ENABLE
#if UART2_RX_DMA_ENABLE
  static uint8_t uart2_rx_dma_buffer[UART2_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart2_rx_dma_buffer = nullptr;
#endif
#if UART2_TX_DMA_ENABLE
  static uint8_t uart2_tx_dma_buffer[UART2_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart2_tx_dma_buffer = nullptr;
#endif
  static uint8_t uart2_rx_buffer[UART2_RX_BUFFER_SIZE];
  static uint8_t uart2_tx_buffer[UART2_TX_BUFFER_SIZE];
  static SimpleBuffer<uint8_t> uart2_rx_sbuffer(uart2_rx_buffer, UART2_RX_BUFFER_SIZE);
  static SimpleBuffer<uint8_t> uart2_tx_sbuffer(uart2_tx_buffer, UART2_TX_BUFFER_SIZE);
  static UART_Object uart2(USART2, UART2_RX_DMA_CH, UART2_TX_DMA_CH,
                          uart2_rx_dma_buffer, UART2_RX_DMA_BUFFER_SIZE,
                          uart2_tx_dma_buffer, UART2_TX_DMA_BUFFER_SIZE,
                          uart2_rx_sbuffer,
                          uart2_tx_sbuffer);
#endif
/*----------------------------------------
 *             UART3 Object
 *-----------------------------------------*/
#if UART3_ENABLE
#if UART3_RX_DMA_ENABLE
  static uint8_t uart3_rx_dma_buffer[UART3_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart3_rx_dma_buffer = nullptr;
#endif
#if UART3_TX_DMA_ENABLE
  static uint8_t uart3_tx_dma_buffer[UART3_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart3_tx_dma_buffer = nullptr;
#endif
  static uint8_t uart3_rx_buffer[UART3_RX_BUFFER_SIZE];
  static uint8_t uart3_tx_buffer[UART3_TX_BUFFER_SIZE];
  static SimpleBuffer<uint8_t> uart3_rx_sbuffer(uart3_rx_buffer, UART3_RX_BUFFER_SIZE);
  static SimpleBuffer<uint8_t> uart3_tx_sbuffer(uart3_tx_buffer, UART3_TX_BUFFER_SIZE);
  static UART_Object uart3(USART3, UART3_RX_DMA_CH, UART3_TX_DMA_CH,
                          uart3_rx_dma_buffer, UART3_RX_DMA_BUFFER_SIZE,
                          uart3_tx_dma_buffer, UART3_TX_DMA_BUFFER_SIZE,
                          uart3_rx_sbuffer,
                          uart3_tx_sbuffer);
#endif
/*----------------------------------------
 *             UART4 Object
 *-----------------------------------------*/
#if UART4_ENABLE
#if UART4_RX_DMA_ENABLE
  static uint8_t uart4_rx_dma_buffer[UART4_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart4_rx_dma_buffer = nullptr;
#endif
#if UART4_TX_DMA_ENABLE
  static uint8_t uart4_tx_dma_buffer[UART4_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *uart4_tx_dma_buffer = nullptr;
#endif
  static uint8_t uart4_rx_buffer[UART4_RX_BUFFER_SIZE];
  static uint8_t uart4_tx_buffer[UART4_TX_BUFFER_SIZE];
  static SimpleBuffer<uint8_t> uart4_rx_sbuffer(uart4_rx_buffer, UART4_RX_BUFFER_SIZE);
  static SimpleBuffer<uint8_t> uart4_tx_sbuffer(uart4_tx_buffer, UART4_TX_BUFFER_SIZE);
  static UART_Object uart4(UART4, UART4_RX_DMA_CH, UART4_TX_DMA_CH,
                          uart4_rx_dma_buffer, UART4_RX_DMA_BUFFER_SIZE,
                          uart4_tx_dma_buffer, UART4_TX_DMA_BUFFER_SIZE,
                          uart4_rx_sbuffer,
                          uart4_tx_sbuffer);
#endif
/*----------------------------------------
 *             UART5
 *-----------------------------------------*/
#if UART5_ENABLE
static uint8_t uart5_rx_buffer[UART5_RX_BUFFER_SIZE];
static uint8_t uart5_tx_buffer[UART5_TX_BUFFER_SIZE];
static SimpleBuffer<uint8_t> uart5_rx_sbuffer(uart5_rx_buffer, UART5_RX_BUFFER_SIZE);
static SimpleBuffer<uint8_t> uart5_tx_sbuffer(uart5_tx_buffer, UART5_TX_BUFFER_SIZE);
static UART_Object uart5(UART5, nullptr, nullptr,
                        nullptr, 0,
                        nullptr, 0,
                        uart5_rx_sbuffer,
                        uart5_tx_sbuffer);
#endif


/**********************************
 *         HAL_UART
 **********************************/
bool HAL_UART::init(uint32_t cfg0)
{
  uint8_t rx_nvic_irqn = 0;
  uint8_t tx_nvic_irqn = 0;
  uint8_t nvic_prio = 0;
  
  cfg = cfg0;
  uint32_t tmp = UART_CFG_EXTRACT(cfg, PORT);
  if(tmp == 0) {  //No port
   return false;
  }
  //UART1
#if UART1_ENABLE
  else if(tmp == UART_PORT(1)) {
    port = (uint32_t)&uart1;
    nvic_prio = NVIC_IRQ_UART1_PRIORITY;
    rx_nvic_irqn = USART1_IRQn;
    //Rx
#if UART1_RX_DMA_ENABLE
    uart1.dma_rx_config();
#else
    uart1.int_rx_config();
#endif
    //Tx
#if UART1_TX_DMA_ENABLE
    uart1.dma_tx_config();
    tx_nvic_irqn = UART1_TX_DMA_CH_IRQN;
#else
    uart1.int_tx_config();  //Not DMA mode, just keep tx_nvic_irqn = 0, because it's same to rx_nvic_irqn
#endif
  }
#endif
    //UART2
#if UART2_ENABLE
  else if(tmp == UART_PORT(2)) {
    port = (uint32_t)&uart2;
    rx_nvic_irqn = USART2_IRQn;
    //Rx
#if UART2_RX_DMA_ENABLE
    uart2.dma_rx_config();
#else
    uart2.int_rx_config();
#endif
    //Tx
#if UART2_TX_DMA_ENABLE
    uart2.dma_tx_config();
    tx_nvic_irqn = UART2_TX_DMA_CH_IRQN;
#else
    uart2.int_tx_config();
#endif
  }
#endif
    //UART3
#if UART3_ENABLE
  else if(tmp == UART_PORT(3)) {
    port = (uint32_t)&uart3;
    rx_nvic_irqn = USART3_IRQn;
    //Rx
#if UART3_RX_DMA_ENABLE
    uart3.dma_rx_config();
#else
    uart3.int_rx_config();
#endif
    //Tx
#if UART3_TX_DMA_ENABLE
    uart3.dma_tx_config();
    tx_nvic_irqn = UART3_TX_DMA_CH_IRQN;
#else
    uart3.int_tx_config();
#endif
  }
#endif
    //UART4
#if UART4_ENABLE
  else if(tmp == UART_PORT(4)) {
    port = (uint32_t)&uart4;
    rx_nvic_irqn = UART4_IRQn;
    //Rx
#if UART4_RX_DMA_ENABLE
    uart4.dma_rx_config();
#else
    uart4.int_rx_config();
#endif
    //Tx
#if UART4_TX_DMA_ENABLE
    uart4.dma_tx_config();
    tx_nvic_irqn = UART4_TX_DMA_CH_IRQN;
#else
    uart4.int_tx_config();
#endif
  }
#endif
    //UART5
#if UART5_ENABLE
  else if(tmp == UART_PORT(5)) {
    port = (uint32_t)&uart5;
    rx_nvic_irqn = UART5_IRQn;
    //Rx
#if UART5_RX_DMA_ENABLE
    uart5.dma_rx_config();
#else
    uart5.int_rx_config();
#endif
    //Tx
#if UART5_TX_DMA_ENABLE
    uart5.dma_tx_config();
    tx_nvic_irqn = UART5_TX_DMA_CH_IRQN;
#else
    uart5.int_tx_config();
#endif
  }
#endif
  else {
    return false;
  }
  
  if(!config(cfg)) {
    return false;
  }
  
  //NVIC config
  NVIC_InitTypeDef   NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = nvic_prio;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  //rx
  if(rx_nvic_irqn > 0) {
    NVIC_InitStructure.NVIC_IRQChannel = rx_nvic_irqn;
    NVIC_Init(&NVIC_InitStructure);
  }
  //tx
  if(tx_nvic_irqn > 0) {
    NVIC_InitStructure.NVIC_IRQChannel = tx_nvic_irqn;
    NVIC_Init(&NVIC_InitStructure);
  }
  return true;
}
/*
*/
bool HAL_UART::config(uint32_t cfg0)
{
  cfg &= ~UART_CFG_MASK;
  cfg |= cfg0 & UART_CFG_MASK;
  return ((UART_Object*)port)->config(cfg);
}
/*
*/
bool HAL_UART::set_baud(uint32_t baud)
{
  cfg &= ~(UART_BAUD_MASK << UART_BAUD_POS);
  cfg |= UART_BAUD(baud) & (UART_BAUD_MASK << UART_BAUD_POS);
  return config(cfg);
}

/*
*/
int HAL_UART::read(uint8_t *buffer, uint32_t num)
{
  return ((UART_Object*)port)->rx_buffer.pop(buffer, num);
}
/*
*/
int HAL_UART::write(uint8_t *buffer, uint32_t num)
{
  int ret = ((UART_Object*)port)->tx_buffer.push(buffer, num);
  ((UART_Object*)port)->send();
  return ret;
}
/*------------------------------------------------
 *             IRQHandler
 *------------------------------------------------*/
#ifdef __cplusplus
 extern "C" {
#endif
/*
*/
#if UART1_ENABLE
void USART1_IRQHandler()
{ 
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  //rx
#if UART1_RX_DMA_ENABLE
  if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  //DMA read
  {
    //clear flag
    USART_ClearITPendingBit(USART1, USART_IT_IDLE);
    uart1.dma_rx_end();
    uart1.dma_rx_start();
  }
#else
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    uart1.int_rx();
  }
#endif
  
  //tx
#if !UART1_TX_DMA_ENABLE
  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(USART1, USART_IT_TXE);
    uart1.int_tx();
  }
#endif
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
#if UART1_TX_DMA_ENABLE
void UART1_TX_DMA_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(DMA_GetITStatus(UART1_TX_DMA_IT_TC))
  {
    DMA_ClearITPendingBit(UART1_TX_DMA_IT_TC);
    uart1.dma_tx_end();
    uart1.dma_tx_start();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif

/*
*/
#if UART2_ENABLE
void USART2_IRQHandler()
{ 
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
   //rx
#if UART2_RX_DMA_ENABLE
  if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  //DMA read
  {
    //clear flag
    USART_ClearITPendingBit(USART2, USART_IT_IDLE);
    uart2.dma_rx_end();
    uart2.dma_rx_start();
  }
#else
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    uart2.int_rx();
  }
#endif
  
  //tx
#if !UART2_TX_DMA_ENABLE
  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(USART2, USART_IT_TXE);
    uart2.int_tx();
  }
#endif
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
#if UART2_TX_DMA_ENABLE
void UART2_TX_DMA_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(DMA_GetITStatus(UART2_TX_DMA_IT_TC))
  {
    DMA_ClearITPendingBit(UART2_TX_DMA_IT_TC);
    uart2.dma_tx_end();
    uart2.dma_tx_start();
  }

#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif
/*
*/
#if UART3_ENABLE
void USART3_IRQHandler()
{ 
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  //rx
#if UART3_RX_DMA_ENABLE
  if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)  //DMA read
  {
    //clear flag
    USART_ClearITPendingBit(USART3, USART_IT_IDLE);
    uart3.dma_rx_end();
    uart3.dma_rx_start();
  }
#else
  if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(USART3, USART_IT_RXNE);
    uart3.int_rx();
  }
#endif
  
  //tx
#if !UART3_TX_DMA_ENABLE
  if(USART_GetITStatus(USART3, USART_IT_TXE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(USART3, USART_IT_TXE);
    uart3.int_tx();
  }
#endif

#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
#if UART3_TX_DMA_ENABLE
void UART3_TX_DMA_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(DMA_GetITStatus(UART3_TX_DMA_IT_TC))
  {
    DMA_ClearITPendingBit(UART3_TX_DMA_IT_TC);
    uart3.dma_tx_end();
    uart3.dma_tx_start();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif
/*
*/
#if UART4_ENABLE
void UART4_IRQHandler()
{ 
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  //rx
#if UART4_RX_DMA_ENABLE
  if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)  //DMA read
  {
    //clear flag
    USART_ClearITPendingBit(UART4, USART_IT_IDLE);
    uart4.dma_rx_end();
    uart4.dma_rx_start();
  }
#else
  if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(UART4, USART_IT_RXNE);
    uart4.int_rx();
  }
#endif
  
  //tx
#if !UART4_TX_DMA_ENABLE
  if(USART_GetITStatus(UART4, USART_IT_TXE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(UART4, USART_IT_TXE);
    uart4.int_tx();
  }
#endif

#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
#if UART4_TX_DMA_ENABLE
void UART4_TX_DMA_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(DMA_GetITStatus(UART4_TX_DMA_IT_TC))
  {
    DMA_ClearITPendingBit(UART4_TX_DMA_IT_TC);
    uart4.dma_tx_end();
    uart4.dma_tx_start();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif

/*
*/
#if UART5_ENABLE
void UART5_IRQHandler()
{ 
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  //rx
  if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(UART5, USART_IT_RXNE);
    uart5.int_rx();
  }
  
  //tx
  if(USART_GetITStatus(UART5, USART_IT_TXE) != RESET)
  {
    //clear flag
    USART_ClearITPendingBit(UART5, USART_IT_TXE);
    uart5.int_tx();
  }

#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif

/*
*/
#ifdef __cplusplus
}
#endif

